package com.mate.cloud.transaction.service;

import com.mate.cloud.common.exception.BusinessRuntimeException;
import com.mate.cloud.transaction.domain.UserVO;
import jakarta.annotation.Resource;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import java.util.Random;

/**
 * 编程式事务
 *
 * @author: MI
 * @email: 448341911@qq.com
 * @createTime: 2024/6/7 18:03
 * @updateUser: MI
 * @updateTime: 2024/6/7 18:03
 * @updateRemark: 修改内容
 * @version: v1.0
 */
@Service
public class TestTransactionService {

    @Resource
    private PlatformTransactionManager transactionManager;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private JdbcTemplate jdbcTemplate;
    Random random = new Random();

    public void testManager() {

        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());

        try {
            String sql = "INSERT INTO `user` (`user_name`, `age`, `create_time`, `create_by`, `update_time`, `update_by`, `STATUS`,`is_del`) VALUES" + " ( '张三', 20, now(), ?, now(), ?, 0, '0') ";

            Object[] objects = new Object[]{String.valueOf(random.nextInt(1000000)), String.valueOf(random.nextInt(1000001))};
            jdbcTemplate.update(sql, objects);
            transactionManager.commit(status);
        } catch (Exception e) {
            transactionManager.rollback(status);
        }
    }

    public void testTemplate() {
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @Override
            protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
                try {
                    String sql = "INSERT INTO `user` (`user_name`, `age`, `create_time`, `create_by`, `update_time`, `update_by`, `STATUS`,`is_del`) VALUES" + " ( '张三', 20, now(), ?, now(), ?, 0, '0') ";
                    Object[] objects = new Object[]{String.valueOf(random.nextInt(1000000)), String.valueOf(random.nextInt(1000001))};
                    jdbcTemplate.update(sql, objects);
                    // ....  业务代码
                } catch (Exception e) {
                    //回滚
                    transactionStatus.setRollbackOnly();
                }

            }
        });
    }

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, rollbackFor = RuntimeException.class, readOnly = false, timeout = -1)
    public String update() {
        return null;

    }

    /**
     * 1、访问权限
     *
     * @param user
     */
    @Transactional
    private void addUser(UserVO user) {
        saveUser(user);
        updateUser(user);
    }

    private void updateUser(UserVO userVO) {
        System.out.println("======================" + userVO);
    }

    private void saveUser(UserVO userVO) {
        System.out.println("======================" + userVO);
    }

    /**
     * 2、方法使用final修饰
     *
     * @param user
     */
    @Transactional
    public final void add(UserVO userVO) {
        saveData(userVO);
    }

    private void saveData(UserVO userVO) {
        System.out.println("======================" + userVO);
    }

    /**
     * 3、方法内部调用
     */
    @Transactional
    public void addUserTx(UserVO userVO) {
        saveData(userVO);
        updateSataus(userVO);
    }


    @Transactional
    public void updateSataus(UserVO userVO) {
        doSomething();
    }

    private void doSomething() {
        System.out.println("======================");
    }

    /**
     * 8、事务的传播特性
     *
     * @param userVO
     */
    @Transactional(propagation = Propagation.NEVER)
    public void addUserVO(UserVO userVO) {
        saveData(userVO);
        updateSataus(userVO);
    }

    /**
     * 9、异常处理
     * <p>这种情况下，因为开发者自己捕获了异常、又没有手动抛出</p>
     *
     * @param userVO
     */
    @Transactional
    public void addEx(UserVO userVO) {
        try {
            saveData(userVO);
            updateSataus(userVO);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 10、自定义回滚异常
     * <p>
     * 但是如果在程序执行过程中，出现了sql异常，但是sql异常并不属于我们定义的BusinessException异常，所以事务也不会回滚</p>
     *
     * @param userModel
     */

    @Transactional(rollbackFor = BusinessRuntimeException.class)
    public void addBusinessRuntimeException(UserVO userVO) {
        saveData(userVO);
        updateSataus(userVO);
    }

}
